﻿/*
 ***************************************************************************
 * Microsoft Visual C# .NET
 * 名称：       Shpm.System.TimeRange
 * 类型：       时间范围类
 * 功能说明：   时间范围类
 * 作者：       王伟栋
 * 创建日期：   2007/11/12
 * 修改日期     修改者      修改内容
 * 
 * 
 * ---
 ***************************************************************************
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;

namespace Shpm.System
{
    public class TimeRange : IComparable
    {
        public const string FORMAT_SHORT_TIME = "HH:mm:ss";
        public const string FORMAT_SIMPLE_HOURS_MINUTES = "HH:mm";

        public static TimeRange MinValue
        {
            get { return new TimeRange(TimeSpan.MinValue, TimeSpan.MinValue); }
        }

        public static TimeRange MaxValue
        {
            get { return new TimeRange(TimeSpan.MinValue, TimeSpan.MaxValue); }
        }

        // public static readonly TimeSpan MaxValue = new TimeRange(TimeSpan.MinValue, TimeSpan.MaxValue);

        /** 开始时间 */
        private TimeSpan beginTime;
        /** 结束时间 */
        private TimeSpan endTime;

        /*
         *名称： TimeRange
         *功能： 构造函数。
         *参数： beginTime - 开始时间
         *       endTime   - 结束时间
         *返回： 
         *说明： 
        */
        public TimeRange(TimeSpan beginTime, TimeSpan endTime)
        {
            this.beginTime = (beginTime < endTime) ? beginTime : endTime;
            this.endTime = (beginTime < endTime) ? endTime : beginTime;
        }

        /*
         *名称： Equals
         *功能： 判断两个对象是否相等。
         *参数： obj - 比较参数
         *返回： 两个对象相等的情况true, 否则false
         *说明： 
        */
        public override bool Equals(object obj)
        {
            if (obj is TimeRange)
            {
                TimeRange val = (TimeRange)obj;

                return (beginTime.Equals(val.beginTime) && endTime.Equals(val.endTime));
            }
            
            return false;
        }

        /*
         *名称： IsRealRange
         *功能： 判断range是否为当前对象的真子集。
         *参数： range - 比较参数
         *返回： 是真子集的情况true, 否则false
         *说明： 
        */
        public bool IsRealRange(TimeRange range)
        {
            return this.Equals(range) == false && this.beginTime <= range.beginTime && range.endTime <= this.endTime;
        }

        /*
         *名称： IsCrossRange
         *功能： 判断当前对象与range是否在开区间上 既不相等也互不为真子集, 并且交集不为空。
         *参数： range - 比较参数
         *返回： 是的情况true, 否则false
         *说明： 
        */
        public bool IsCrossRange(TimeRange range)
        {
            return (this.beginTime < range.beginTime && range.beginTime < this.endTime) ^ (this.beginTime < range.endTime && range.endTime < this.endTime);
        }

        /*
         *名称： GetHashCode
         *功能： 返回对象的HashCode。
         *参数： 无
         *返回： 对象的HashCode
         *说明： 
        */
        public override int GetHashCode()
        {
            string key = string.Format("{0} - {1}", this.beginTime.Ticks, this.endTime.Ticks);

            return key.GetHashCode();
        }

        /*
         *名称： ToString
         *功能： 取得对象的字符串形式。
         *参数： 无
         *返回： 对象的字符串形式
         *说明： 
        */
        public override string ToString()
        {
            string s = string.Format("{0} - {1}", this.beginTime.ToString(), this.endTime.ToString());

            return s;
        }

        /*
         *名称： ToString
         *功能： 取得对象的字符串形式。
         *参数： format - 格式化字符串
         *返回： 对象的字符串形式
         *说明： 
        */
        public string ToString(string format)
        {
            string s = string.Empty;

            if (TimeRange.MinValue.Equals(this) || TimeRange.MaxValue.Equals(this))
            {
                s = Shpm.System.Constants.EMPTY_STRING;
            }
            else 
            {
                DateTime d1 = new DateTime(this.beginTime.Ticks);
                DateTime d2 = new DateTime(this.endTime.Ticks);

                s = string.Format("{0} - {1}", d1.ToString(format), d2.ToString(format));
            }

            return s;
        }

        /*
         *名称： UnionTimeRange
         *功能： 合并两个时间范围(取r1,r2中最小的为左边界, 最大的为右边界)。
         *参数： r1 - 时间范围1
         *       r2 - 时间范围2
         *返回： 合并後的时间范围
         *说明： 
        */
        public static TimeRange UnionTimeRange(TimeRange r1, TimeRange r2)
        {
            ArrayList list = new ArrayList();

            list.Add(r1.beginTime);
            list.Add(r1.endTime);
            list.Add(r2.beginTime);
            list.Add(r2.endTime);

            list.Sort();

            TimeRange range = new TimeRange((TimeSpan)list[0], (TimeSpan)list[3]);
            return range;
        }

        /*
         *名称： Parse
         *功能： 根据字符串解析到时间范围对象。
         *参数： s - 包含要转换的值的字符串
         *返回： 时间范围对象
         *说明： 
        */
        public static TimeRange Parse(string s)
        {
            TimeRange range = null;

            Regex reg = new Regex("^([0-9:\\.]+)[\\s]*-[\\s]*([0-9:\\.]+)$");

            Match m = reg.Match(s);

            if (m.Groups.Count != 3)
            {
                throw new FormatException(s);
            }
            else
            {
                try
                {
                    range = new TimeRange(TimeSpan.Parse(m.Groups[1].Value), TimeSpan.Parse(m.Groups[2].Value));
                }
                catch (Exception e)
                {
                    throw new FormatException(e.Message);
                }
            }

            return range;
        }

        /*
         *名称： CompareTo
         *功能： 将此实例与指定对象进行比较并返回一个对二者的相对值的指示。
         *参数： obj - 要与此实例比较的对象。
         *返回： 一个有符号的整数，它指示此实例和 obj 的相对顺序
         *说明： 
        */
        public int CompareTo(object obj)
        {
            if (obj is TimeRange)
            {
                TimeRange tmp = (TimeRange)obj;

                return (this.beginTime.CompareTo(tmp.beginTime)==0)?this.endTime.CompareTo(tmp.endTime):this.beginTime.CompareTo(tmp.beginTime);    
            }

            throw new ArgumentException("object is not a TimeRange");
        }

        /** 开始时间 */
        public TimeSpan BeginTime
        {
            get { return beginTime; }
        }

        /** 结束时间 */
        public TimeSpan EndTime
        {
            get { return endTime; }
        }


    }
}
